#include "mainwindow.h"
#include "./ui_mainwindow.h"
#include <QMessageBox>
#include <QDebug>
#include <QtWidgets>
#include <QIcon>

#include <cstring>
#include "Parameter.h"
#include "zd60_control.h"
#include "power_board.h"
#include "data_chart.h"

QSerialPort *serialPort;


ZD60_Control *zd60control;
Power_board *power_board;
Data_chart *data_chart;

// 计算Modbus CRC16校验值，返回unsigned short类型
unsigned short modbusCRC16(const QByteArray& packet,int len)
{
    unsigned short crc = 0xFFFF;
    for (int i = 0; i < len; ++i)
    {
        crc ^= static_cast<unsigned char>(packet[i]);
        for (int j = 0; j < 8; ++j)
        {
            if (crc & 0x0001)
            {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}


// 计算Modbus CRC16校验值，返回unsigned short类型
unsigned short CRC(uint8_t *packet,int len)
{
    unsigned short crc = 0xFFFF;
    for (int i = 0; i < len; ++i)
    {
        crc ^= static_cast<unsigned char>(packet[i]);
        for (int j = 0; j < 8; ++j)
        {
            if (crc & 0x0001)
            {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    return crc;
}

uint8_t buffer[145];






MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    // 设置默认样式
    QApplication::setStyle(QStyleFactory::create("Fusion"));
    QPalette palette;
    //设置主窗口背景颜色
    palette.setColor(QPalette::Window,QColor(220,226,241));
    this->setPalette(palette);

    // mainLayout = new QVBoxLayout(this);

    ui->setupUi(this);
    serialPort = new QSerialPort(this); // 初始化一个串口实例
    updateSerialPortList();  // 刷新串口号
    // setWindowFlags(Qt::CustomizeWindowHint|Qt::FramelessWindowHint);hide();
    zd60control = new ZD60_Control(this);
    power_board = new Power_board(this);
    data_chart = new Data_chart(this);

    ui->stackedWidget->addWidget(zd60control);
    ui->stackedWidget->addWidget(power_board);
    ui->stackedWidget->addWidget(data_chart);
    zd60control->close();
    power_board->close();
    data_chart->close();
    ui->stackedWidget->setCurrentIndex(0);
    // bootloader
    // 创建一个定时器
    timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &MainWindow::timer_callback);
    timer->start(1);
    setWindowTitle("探索鹰串口调试工具 V1.4.1");//serial  在Mywidget头文件中
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::set_ui_type(void)
{
    // 准备图片文件，可以放在资源文件中或者通过文件路径加载
    //QPixmap pixmap("E:\WORK\Program\QT\ASD_Warm_Show\TSY.png");
    // 或者使用绝对路径加载图片
    // QPixmap pixmap("E:/WORK/Program/_app_qt/ASD_Warm_Show/TSY.png");
}

/*
    打开折叠版60界面
*/
void MainWindow::on_XTY_zd60test_show_clicked()
{
    // QPalette palette;
    // //设置主窗口背景颜色
    // palette.setColor(QPalette::Window,QColor(255,0,0));
    // zd60control->setPalette(palette);

    // zd60control->move(160,24);
    ui->stackedWidget->setCurrentIndex(1);

    // ui->label_8->setText("60折叠版测试");
}
/*
    打开串口界面
*/
void MainWindow::on_pushButton_serial_clicked()
{
    ui->stackedWidget->setCurrentIndex(0);

}

/*
    打开功率板界面
*/
void MainWindow::on_pushButton_power_show_clicked()
{
    ui->stackedWidget->setCurrentIndex(2);
    power_board->show_power();

}
/*
    打开绘图界面
*/
void MainWindow::on_chart_show_clicked()
{
     ui->stackedWidget->setCurrentIndex(3);
}


/*
    在UI界面上刷新串口编号
*/
void MainWindow::updateSerialPortList()
{
    ui->comboBox_2->clear();
    foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        ui->comboBox_2->addItem(info.portName());
    }
}

/*
    刷新串口按键槽函数
*/
void MainWindow::on_RfSerialButton_clicked()
{
    updateSerialPortList();
}

void MainWindow::showupdateData()
{

    // if(BoardP.DRDY == 1)  // 数据更新，同步更新显示
    // {
    //     page_show->ShowBoardData(BoardP);
    //     BoardP.DRDY = 0;
    // }
}

void MainWindow::on_openSerialButton_clicked()
{
    if (serialPort->isOpen())
    {
        qDebug()<<"close com ";
        serialPort->close();
        ui->openSerialButton->setText("打开串口");
        isSerialPortOpen = false;
        update_status = 0;
    }
    else
    {
        QString portName = ui->comboBox_2->currentText();
        serialPort->setPortName(portName);
        serialPort->setBaudRate(QSerialPort::Baud115200);
        serialPort->setDataBits(QSerialPort::Data8);
        serialPort->setParity(QSerialPort::NoParity);
        serialPort->setStopBits(QSerialPort::OneStop);
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
        if (serialPort->open(QIODevice::ReadWrite))
        {
            qDebug()<<"open com "<<portName<<" success";
            ui->openSerialButton->setText("关闭串口");
            connect(serialPort,&QSerialPort::readyRead,this,&MainWindow::DataReady);
            isSerialPortOpen = true;
        }
        else
        {
            qDebug()<<"open com "<<portName<<" faile";
            QMessageBox msgBox;
            msgBox.setText(QString("串口 %1 打开失败").arg(portName));
            msgBox.exec();
            isSerialPortOpen = false;
        }
    }
}


/*
 * 开始升级按键槽函数
 */
void MainWindow::on_button_start_iap_clicked()
{

    if(isFineOpen)
    {
        // 设置初始值
        ui->progressBar->setMaximum(numPackets-1);
        // 发送需要更新指令
        sendUpdateCommandPacket();
        // 改变状态位
        update_status = 1;
    }
}
/*
 * 定时器回调函数
*/
void MainWindow::timer_callback()
{
    if(update_status)
    {
        ResendTimeNum ++;
        if(ResendTimeNum >3000)
        {
            //清空计数
            ResendTimeNum = 0;  // 清空重发计数
            // 获取系统时间
            QDateTime currentTime = QDateTime::currentDateTime();
            //重新发送数据包
            if(update_status == 1)
            {
                ui->label_information->setText(currentTime.toString("yyyy-MM-dd hh:mm:ss")+QString("：请求超时！重发升级请求！"));
                sendUpdateCommandPacket();
            }
            else if(update_status == 2)
            {
                // 显示时间和超时信息
                ui->label_information->setText(currentTime.toString("yyyy-MM-dd hh:mm:ss")+QString("：超时！重发数据包：%1").arg(currentPacket));
                sendUpdatePromPacket(currentPacket); // 发送程序文件
            }
        }
    }
    else
    {}
    if(isSerialPortRec == true)
    {
        SerialPort_RecNum ++;
        if(SerialPort_RecNum > 10)
        {
            SerialPort_RecNum = 0;
            isSerialPortRec = false;
            serialPort_callback();   // 接收到数据一定时间后才开始处理
            //qDebug()<<"handle serial port data"<<isSerialPortRec;
        }
    }
    else
    {
    }
}
/*
    串口接收处理
*/
void MainWindow::DataReady()
{
    isSerialPortRec = true;
    SerialPort_RecNum = 0;  // 有新的数据清除超时计数
    //qDebug()<<"recive serial port data"<<isSerialPortRec;
}

/*
 * 串口回调函数
*/
void MainWindow::serialPort_callback()
{
    int DataLen = 0;
    DataLen = serialPort->bytesAvailable();
    qDebug()<<"len : "<< DataLen;
    QByteArray dir_data;
    QByteArray receivedData =serialPort->readAll();
    unsigned short FrameLen = 0;
    appendDataToTextEdit(receivedData);
    for(int i = 0;i<DataLen;)
    {
        if(receivedData[i] == (char)0xe9 && receivedData[(i+1)] == (char)0x90 &&(DataLen-i) >8)
        {

            FrameLen |= ((receivedData[(i+6)]& 0x00FF)<<8);
            FrameLen |= (receivedData[(i+7)]& 0x00FF);
            if(FrameLen <= (DataLen-2-i))  // 数据长度接收没有异常
            {
                // 截取从第i个字节开始的子数组
                QByteArray Packet = receivedData.mid(i, (FrameLen+2));
                unsigned short crc16_rx = modbusCRC16(Packet,FrameLen);
                unsigned short crc16_data = 0;
                crc16_data |= ((Packet[(FrameLen)]& 0x00FF)<<8);
                crc16_data |= (Packet[(FrameLen+1)]& 0x00FF);
                // qDebug()<<"crc16_rx"<< crc16_rx<<"crc16_rx"<<crc16_data;
                if(crc16_rx == crc16_data)
                {
                    // qDebug()<<"e990data crc check ok ";
                    unsigned short FramType = 0;
                    FramType |= ((receivedData[(i+4)]& 0x00FF)<<8);
                    FramType |= (receivedData[(i+5)]& 0x00FF);
                    //qDebug()<<"FramType："<<FramType;
                    if((FramType&0xf000) == DTU_MASTER_TYPE_RX)
                    {

                    }
                    else if((FramType&0xff00) == 0x0000)
                    {
                        ui->label_information->clear();  // 收到数据清空超时提示
                        //qDebug()<<"Boot";
                        switch ((unsigned char)FramType) {
                        case 0x62:    // 收到更新指令反馈
                        {
                            update_status = 2;  // 改变状态位
                            currentPacket = 0;  // 从第0包数据开始
                            ResendTimeNum = 0;  // 清空计数
                            sendUpdatePromPacket(currentPacket); // 发送程序文件
                            qDebug()<<"板子收到更新指令";
                        }
                            break;
                        case 0x63:
                        {
                            unsigned short CurrentPacketNum = 0;
                            CurrentPacketNum |= ((receivedData[(i+8)]& 0x00FF)<<8);
                            CurrentPacketNum |= (receivedData[(i+9)]& 0x00FF);
                            qDebug()<<"收到请求数据包num ="<<CurrentPacketNum;
                            if(CurrentPacketNum < (numPackets)) // 判读是否超限
                            {
                                currentPacket = CurrentPacketNum;  // 收到包号请求
                                sendUpdatePromPacket(currentPacket); // 发送程序文件
                                ResendTimeNum = 0;  // 清空计数
                                ui->progressBar->setValue(currentPacket); // 更新提示信息
                                ui->label_info->setText(QString("升级中...当前包号：%1 总包数：%2").arg(currentPacket).arg(numPackets));
                            }
                            else
                            {
                                update_status = 0;  // 升级完成，改变状态位
                                QMessageBox::information(this, "提示", "升级完成！");
                                ui->label_info->setText(QString("升级完成 总包数：%1").arg(numPackets));
                            }
                        }
                            break;
                        case 0x01:
                            powerdata.V_CH1 = (float)(((receivedData[i+8]&0x00FF)<<8)|(receivedData[i+9]&0x00FF))/4096*3.3f/3*V_num ;
                            if(powerdata.V_CH1<0)
                                powerdata.V_CH1 = 0;
                            powerdata.V_CH2 = (float)(((receivedData[i+10]&0x00FF)<<10)|(receivedData[i+11]&0x00FF))/4096*3.3f/3*V_num ;
                            if(powerdata.V_CH2<0)
                                powerdata.V_CH2 = 0;
                            powerdata.V_CH3 = (float)(((receivedData[i+12]&0x00FF)<<8)|(receivedData[i+13]&0x00FF))/4096*3.3f/3*V_num ;
                            if(powerdata.V_CH3<0)
                                powerdata.V_CH3 = 0;
                            powerdata.V_CH4 = (float)(((receivedData[i+14]&0x00FF)<<8)|(receivedData[i+15]&0x00FF))/4096*3.3f/3*V_num ;
                            if(powerdata.V_CH4<0)
                                powerdata.V_CH4 = 0;
                            powerdata.C_CH1 = ((((float)(((receivedData[i+16]&0x00FF)<<8)|(receivedData[i+17]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH1<0)
                                powerdata.C_CH1 = 0;
                            powerdata.C_CH2 = ((((float)(((receivedData[i+18]&0x00FF)<<8)|(receivedData[i+19]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH2<0)
                                powerdata.C_CH2 = 0;
                            powerdata.C_CH3 = ((((float)(((receivedData[i+20]&0x00FF)<<8)|(receivedData[i+21]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH3<0)
                                powerdata.C_CH3 = 0;
                            powerdata.C_CH4 = ((((float)(((receivedData[i+22]&0x00FF)<<8)|(receivedData[i+23]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH4<0)
                                powerdata.C_CH4 = 0;
                            powerdata.C_CH5 = ((((float)(((receivedData[i+24]&0x00FF)<<8)|(receivedData[i+25]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH5<0)
                                powerdata.C_CH5 = 0;
                            powerdata.C_CH6 = ((((float)(((receivedData[i+26]&0x00FF)<<8)|(receivedData[i+27]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH6<0)
                                powerdata.C_CH6 = 0;
                            powerdata.C_CH7 = ((((float)(((receivedData[i+28]&0x00FF)<<8)|(receivedData[i+29]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH7<0)
                                powerdata.C_CH7 = 0;
                            powerdata.C_CH8 = ((((float)(((receivedData[i+30]&0x00FF)<<8)|(receivedData[i+31]&0x00FF))/4096*3.3f/3*5)/249)*1000-4)/16*C_num;
                            if(powerdata.C_CH8<0)
                                powerdata.C_CH8 = 0;
                            power_board->show_power();
                            break;
                        default:
                            qDebug()<<"无效数据包";
                            break;
                        }
                    }
                    else if((FramType&0x00ff) == 0x0068)    //反馈电机状态
                    {
                        switch((FramType>>8)&0x00ff)
                        {
                            case ZJB1_flag:
                                zd60control->show_ZD60_Motor_statue(ZJB1_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case ZJB2_flag:
                                zd60control->show_ZD60_Motor_statue(ZJB2_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case YJB1_flag:
                                zd60control->show_ZD60_Motor_statue(YJB1_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case YJB2_flag:
                                zd60control->show_ZD60_Motor_statue(YJB2_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case ZFYC1_flag:
                                zd60control->show_ZD60_Motor_statue(ZFYC1_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case ZFYC2_flag:
                                zd60control->show_ZD60_Motor_statue(ZFYC2_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case YFYC1_flag:
                                zd60control->show_ZD60_Motor_statue(YFYC1_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case YFYC2_flag:
                                zd60control->show_ZD60_Motor_statue(YFYC2_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case ZFYX1_flag:
                                zd60control->show_ZD60_Motor_statue(ZFYX1_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case ZFYX2_flag:
                                zd60control->show_ZD60_Motor_statue(ZFYX2_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case YFYX1_flag:
                                zd60control->show_ZD60_Motor_statue(YFYX1_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case YFYX2_flag:
                                zd60control->show_ZD60_Motor_statue(YFYX2_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case Battery_flag:
                                zd60control->show_ZD60_Motor_statue(Battery_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case Pod_flag:
                                zd60control->show_ZD60_Motor_statue(Pod_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case CT_flag:
                                zd60control->show_ZD60_Motor_statue(CT_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;
                            case FDJ_flag:
                                zd60control->show_ZD60_Motor_statue(FDJ_flag,(uint8_t)(receivedData[(i+3)]& 0x00FF));
                                break;

                            default:

                                break;
                        }

                    }
                }
                else
                {
                    qDebug()<<"e990data crc check err ";
                }
                i+=(FrameLen+2);
            }
            else
            {
                break;
                i+=DataLen;
            }
        }
        else if(receivedData[i] == (char)0x5A && receivedData[(i+1)] == (char)0xA5 &&(DataLen-i) >8)
        {
            FrameLen |= ((receivedData[(i+4)]& 0x00FF)<<8);
            FrameLen |= (receivedData[(i+5)]& 0x00FF);
            if(FrameLen <= (DataLen-2-i))  // 数据长度接收没有异常
            {
                // 截取从第i个字节开始的子数组
                QByteArray Packet = receivedData.mid(i, (FrameLen+2));
                unsigned short crc16_rx = modbusCRC16(Packet,FrameLen);
                unsigned short crc16_data = 0;
                crc16_data |= ((Packet[(FrameLen)]& 0x00FF)<<8);
                crc16_data |= (Packet[(FrameLen+1)]& 0x00FF);
                // qDebug()<<"crc16_rx"<< crc16_rx<<"crc16_rx"<<crc16_data;
                if(crc16_rx == crc16_data)
                {
                    unsigned short FramType = 0;

                    FramType |= (receivedData[(i+3)]& 0x00FF);
                    if((FramType&0x00ff) == 0x0066)
                    {
                        zd60control->show_ZD60_Motor_statue(ZJB1_flag,(uint8_t)(receivedData[(i+6)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(ZJB2_flag,(uint8_t)(receivedData[(i+7)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(YJB1_flag,(uint8_t)(receivedData[(i+8)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(YJB2_flag,(uint8_t)(receivedData[(i+9)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(ZFYC1_flag,(uint8_t)(receivedData[(i+10)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(ZFYC2_flag,(uint8_t)(receivedData[(i+11)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(YFYC1_flag,(uint8_t)(receivedData[(i+12)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(YFYC2_flag,(uint8_t)(receivedData[(i+13)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(ZFYX1_flag,(uint8_t)(receivedData[(i+14)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(ZFYX2_flag,(uint8_t)(receivedData[(i+15)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(YFYX1_flag,(uint8_t)(receivedData[(i+16)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(YFYX2_flag,(uint8_t)(receivedData[(i+17)]& 0x00FF));
                        zd60control->show_ZD60_Motor_statue(Battery_flag,(uint8_t)(receivedData[(i+18)]& 0x00FF));
                    }
                }
                else
                {
                    qDebug()<<"5AA5data crc check err ";
                }
                i+=(FrameLen+2);
            }

        }
        else
        {
            i++;
            //qDebug()<<"err ";
        }
    }
}
/*
    将传入的数据在textEdit_rx上显示
*/
void MainWindow::appendDataToTextEdit(const QByteArray &data)
{
    QString time_stamp = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss.zzz") + " RX: ";
    // serial_ui->textEdit_rx->append(time_stamp);
    // QString formattedData;
    QString formattedData = time_stamp + QString::fromUtf8(data);
    // 显示方式，hex/ascii
    if (ui->checkBox->isChecked())
    {
        ui->textEdit_rx->insertPlainText(formattedData);

    } else
    {
        ui->textEdit_rx->append(time_stamp);
        formattedData.clear();
        for (char c : data)
        {
            formattedData += QString("%1 ").arg(static_cast<unsigned char>(c), 2, 16, QLatin1Char('0')).toUpper();
        }
        ui->textEdit_rx->insertPlainText(formattedData);
    }
    ui->textEdit_rx->moveCursor(QTextCursor::End);

}

/*
 * 通过串口发送数据包
 */
void MainWindow::sendPacket(const QByteArray &data)
{
    if (serialPort->isOpen())
    {
        // 通过串口写数据
        serialPort->write(data);
    }
    else
    {
        QMessageBox::critical(this, "错误", "串口未打开，无法发送数据。");
    }
}

void MainWindow::on_ClearSerialButton_rx_clicked()
{
    // 清除接收框的数据
    ui->textEdit_rx->clear();
}
/*
 * 保存接收框的数据到txt文件
 */
void MainWindow::on_SaveSerialButton_rx_clicked()
{
    QString filePath = QFileDialog::getSaveFileName(this, "保存数据", "", "文本文件 (*.txt)");
    if (!filePath.isEmpty()) {
        QFile file(filePath);
        if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
            QTextStream out(&file);
            out << ui->textEdit_rx->toPlainText();
            file.close();
        }
    }
    //保存接收框的数据到txt文件

}
void MainWindow::dtu_send_command_packet(unsigned short frame_type)
{
    QByteArray packet;
    unsigned short Modbus_crc16 =0;
    packet.append((char)0xe9);
    packet.append((char)0x90);  // 包头
    packet.append((char)0x00);
    packet.append((char)0x01);  // 板子ID
    packet.append((char)(frame_type>>8));
    packet.append((char)(frame_type&0xff));  // 数据类型
    unsigned short dala_len = 8;
    packet.append((char)(dala_len>>8));
    packet.append((char)(dala_len>>0));
    Modbus_crc16 = modbusCRC16(packet,dala_len);
    packet.append((char)(Modbus_crc16>>8));
    packet.append((char)(Modbus_crc16>>0));
    sendPacket(packet);
}
void MainWindow::dtu_ReadFile_packet(unsigned short frame_type,int FileIdex)
{
    QByteArray packet;
    unsigned short Modbus_crc16 =0;
    packet.append((char)0xe9);
    packet.append((char)0x90);  // 包头
    packet.append((char)0x00);
    packet.append((char)0x01);  // 板子ID
    packet.append((char)(frame_type>>8));
    packet.append((char)(frame_type&0xff));  // 数据类型
    unsigned short dala_len = 10;
    packet.append((char)(dala_len>>8));
    packet.append((char)(dala_len>>0));
    packet.append((char)(FileIdex>>8));
    packet.append((char)(FileIdex>>0));
    Modbus_crc16 = modbusCRC16(packet,dala_len);
    packet.append((char)(Modbus_crc16>>8));
    packet.append((char)(Modbus_crc16>>0));
    sendPacket(packet);
}
/*
    数据转换
*/
QString MainWindow::PritfQByteArray(QByteArray aData)
{

    QString strArray =QString(aData.toHex()).toUpper();
    for(int i =2;i<strArray.length();i+=3)
    {
        strArray.insert(i,' ');
    }
    return strArray;
}
/*
 * 打开文件夹
 */
void MainWindow::openHexFile()
{
    QString folderPath = QDir::currentPath();
    QString fileName = QFileDialog::getOpenFileName(this, "打开 BIN 文件", folderPath, "BIN 文件 (*.bin)");
    if (!fileName.isEmpty())
    {
        // 实例化一个文件对象
        QFile file(fileName);
        // 打开文件
        if (!file.open(QIODevice::ReadOnly))
        {
            QMessageBox::critical(this, "错误", "无法打开文件：" + fileName);
            return;
        }
        // 读出所有数据
        hexData = file.readAll();
        // 关闭文件
        file.close();
        // 得到总包数
        numPackets = hexData.length() / packetSize + ((hexData.length() % packetSize) > 0? 1 : 0);
        // 在label控件上显示待升级文件名字
        QFileInfo fileInfo(fileName);
        ui->filePathLabel->setText("当前文件："+fileInfo.fileName());
        // 初始化升级进度和提示
        currentPacket = 0;
        ui->progressBar->setValue(currentPacket);
        ui->label_info->setText(QString("当前包号：%1 总包数：%2").arg(currentPacket).arg(numPackets));
        // 标记文件已经打开
        isFineOpen = true;
    }
}
unsigned short MainWindow::chooseBoard()
{
    unsigned short Board_Index =0;
    // 获取当前选中的文本
    QString selectedText = ui->comboBox_6->currentText();
    // 比较选中的文本与"MASTER"和"SLAVE"
    if (selectedText == "MASTER") {
        Board_Index = DTU_MASTER_TYPE_TX;
    } else if (selectedText == "SLAVE") {
        Board_Index = DTU_SLAVE_TYPE_TX;
    } else {
        Board_Index = OTHER_TYPE_TX;
    }
    qDebug()<<"[MASHER]";
    return Board_Index;
}

/*
 * 发送请求更新指令
 */
void MainWindow::sendUpdateCommandPacket()
{
    // 数据包1
    QByteArray packet1Data = preparePacket(0x0060,numPackets);
    // 打印调试信息
    qDebug()<<"CPacket: "<<currentPacket<<" Num:"<<numPackets;
    // 发送
    sendPacket(packet1Data);
    // 更新提示信息
    ui->label_info->setText(QString("发送升级请求 本次升级总包数：%1").arg(numPackets));
}

/*
 * 发送程序数据包
 */
void MainWindow::sendUpdatePromPacket(int packetNumber)
{
    // 数据包2组包
    QByteArray packet2Data = preparePacket(0x0061,packetNumber);
    // 发送
    sendPacket(packet2Data);
}
/*
 * 将数据包打包成对应格式
 */
QByteArray MainWindow::preparePacket(unsigned short frame_type,int packetNumber)
{
    QByteArray packet;
    unsigned short Board_Type = chooseBoard();
    unsigned short packetType = (Board_Type|frame_type);
    packet.append((char)0xe9);
    packet.append((char)0x90);  // 包头
    packet.append((char)0x00);
    packet.append((char)0x01);  // 待升级板子ID
    packet.append((char)(packetType>>8));
    packet.append((char)(packetType&0xff));  // 数据类型
    unsigned short dala_len = 0;
    switch (frame_type) {
    case 0x0060:
        dala_len = 10;
        packet.append((char)(dala_len>>8));
        packet.append((char)(dala_len&0xff));  // 数据长度
        packet.append((char)(numPackets>>8));
        packet.append((char)(numPackets&0xff));  // 总包号
        break;
    case 0x0061:
        dala_len = packetSize+10;
        packet.append((char)(dala_len>>8));
        packet.append((char)(dala_len&0xff));  // 数据长度
        packet.append((char)(currentPacket>>8));
        packet.append((char)(currentPacket&0xff));  // 当前包号
        if (packetNumber == numPackets - 1) {
            // 最后一个数据包
            QByteArray lastPacketData = hexData.mid(packetNumber * packetSize);
            int remainingSize = packetSize - lastPacketData.size();
            packet.append(lastPacketData);
            for (int i = 0; i < remainingSize; i++) {
                packet.append((char)0xff);
            }
        } else {
            packet.append(hexData.mid(packetNumber * packetSize, packetSize));
        }
        break;
    case 0x0003:
        dala_len = 10;
        packet.append((char)(dala_len>>8));
        packet.append((char)(dala_len&0xff));  // 数据长度
        packet.append((char)(0x00));
        packet.append((char)(0xff));  //
        break;
    default:
        break;
    }
    // 计算 CRC16_MBUS
    unsigned short crc = modbusCRC16(packet, packet.length());
    packet.append((char)(crc >> 8));
    packet.append((char)(crc & 0xff));// crc
    //qDebug()<<"TX Paket Len="<<packet.length()<<":"<<PritfQByteArray(packet);
    qDebug()<<"发送程序包，包号:"<<packetNumber;
    return packet;
}
/*
 * 打开文件按键槽函数
 */
void MainWindow::on_openButton_clicked()
{
    // 打开待升级文件
    openHexFile();
}


